package dmwr.repo.gae;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.FilterOperator;

import dmwr.bean.Pool;
import dmwr.repo.PoolRepo;

public class PoolRepoGae implements PoolRepo {
	private static final Logger log = Logger.getLogger(PoolRepoGae.class
			.getName());
	private static final String KIND = "Pool";
	private static final String PROPERTY_TITLE = "title";
	private static final String PROPERTY_CREATED = "created";

	@Override
	public List<Pool> list(int offset, int limit) {
		return pools(new Query(KIND).addSort(PROPERTY_CREATED,
				Query.SortDirection.ASCENDING), offset, limit);
	}

	@Override
	public Pool byId(Long id) {
		Key key = KeyFactory.createKey(KIND, id);
		Pool item;
		try {
			item = pool(Gae.datastoreService().get(key));
		} catch (EntityNotFoundException e) {
			item = null;
		}
		log.info("pool byId " + id + " " + item);
		return item;
	}

	@Override
	public void save(Pool pool) {
		Entity entity;
		if (pool.getId() == null) {
			entity = new Entity(KIND);
			entity.setProperty(PROPERTY_CREATED, System.currentTimeMillis());
		} else {
			// entity = new Entity(KIND, pool.getId());
			Key key = KeyFactory.createKey(KIND, pool.getId());
			try {
				entity = Gae.datastoreService().get(key);
			} catch (EntityNotFoundException e) {
				throw new RuntimeException(e);
			}
		}
		entity.setProperty(PROPERTY_TITLE, pool.getTitle());
		Gae.datastoreService().put(entity);
		if (pool.getId() == null) {
			pool.setId(entity.getKey().getId());
		}
	}

	@Override
	public void delete(Long id) {
		Key key = KeyFactory.createKey(KIND, id);
		Gae.datastoreService().delete(key);
	}

	@Override
	public Pool byTitle(String title) {
		return pool(new Query(KIND).setFilter(
				FilterOperator.EQUAL.of(PROPERTY_TITLE, title)).addSort(
				PROPERTY_CREATED, Query.SortDirection.ASCENDING));
	}

	private List<Pool> pools(Query query, int offset, int limit) {
		List<Entity> results = Gae.datastoreService().prepare(query)
				.asList(FetchOptions.Builder.withOffset(offset).limit(limit));
		List<Pool> list = new ArrayList<Pool>(results.size());
		for (Entity result : results) {
			list.add(pool(result));
		}
		return list;
	}

	private Pool pool(Query query) {
		List<Entity> results = Gae.datastoreService().prepare(query)
				.asList(FetchOptions.Builder.withLimit(1));
		Entity result = !results.isEmpty() ? results.get(0) : null;
		return pool(result);
	}

	private Pool pool(Entity result) {
		return result != null ? new Pool(result.getKey().getId(),
				(String) result.getProperty(PROPERTY_TITLE),
				(Long) result.getProperty(PROPERTY_CREATED)) : null;
	}
}
